﻿using System.Collections.Generic;
using Engine;
using Engine.Graphics;
using Game;
using static Mekiasm.MekBlock;
using static Mekiasm.MekCraftingRecipe;

namespace Mekiasm
{
    public abstract class Item
    {//模拟block
        public int itemIndex;
        public int blockValue;
        public string DisplayName = string.Empty;
        public string Description = string.Empty;
        public string Category = MekiasmInit.categories_base_item;

        public Game.Random random = new Game.Random();

        public Item(string name)
        {
            DisplayName = name;
        }

        public virtual int MakeBlockValue(int index, int itemIndex)
        {
            return Terrain.MakeBlockValue(index, 0, itemIndex);
        }
        
        public virtual void Initilize() { }

        public virtual void GetProceduralCraftingRecipes(List<CraftingRecipe> recipes)
        {

        }
        public virtual int GetTextureSlotCount(int value) {
            return 16;
        }
        public virtual Texture2D GetTexture()
        {
            return null;
        }

        public virtual int GetCraftedRemainValue(int value)
        {
            return 0;
        }

        public virtual int GetCraftedResultValue(int value)
        {
            return value;
        }

        public virtual ClothingData GetClothingData()
        {
            return null;
        }

        public virtual bool OnAim(Ray3 aim, ComponentMiner componentMiner, AimState state)
        {
            return false;
        }
        public virtual float GetBlockHealth(int value)
        {
            return -1f;
        }
        public virtual Vector3 GetFirstPersonRotation(int value)
        {
            return Vector3.Zero;
        }
        public virtual Vector3 GetFirstPersonOffset(int value)
        {
            return new Vector3(0.5f, -0.5f, -0.6f);
        }
        public virtual Vector3 GetInHandRotation(int value)
        {
            return Vector3.Zero;
        }
        public virtual Vector3 GetInHandOffset(int value)
        {
            return Vector3.Zero;
        }
        public virtual bool IsClothing()
        {
            return false;
        }
        public virtual void ClothingEquiped(int value, ComponentPlayer componentPlayer)
        {

        }
        public virtual void ClothingUnEquiped(int value, ComponentPlayer componentPlayer)
        {

        }
        public virtual void ClothingEquipedUpdate(int value, ComponentPlayer componentPlayer)
        {

        }
        public virtual int GetMaxStacking()
        {
            return 40;
        }
        public virtual int GetEmittedLightAmount(int value)
        {

            return 0;
        }
        public virtual PlantSystem.PlantItem GetPlantItem(int value, int x, int y, int z)
        {
            return null;
        }
        public virtual bool IsCollidable(int value)
        {
            return false;
        }
        public void DisplayMsg(ComponentMiner miner, string msg)
        {
            miner.ComponentPlayer.ComponentGui.DisplaySmallMessage(msg, Color.White, false, false);
        }

        public void DisplayMsg(ComponentPlayer player, string msg)
        {
            player.ComponentGui.DisplaySmallMessage(msg, Color.White, false, false);
        }
        public void DisplayMsg(ComponentPlayer player, string msg, Color color)
        {
            player.ComponentGui.DisplaySmallMessage(msg, color, false, false);
        }
        public virtual bool IsFood()
        {
            return false;

        }
        public virtual bool OnEditInventoryItem(int value, IInventory inventory, int slotIndex, ComponentPlayer componentPlayer)
        {
            DisplayMsg(componentPlayer,"该物品无法进行编辑");
            return true;
        }
        public virtual BlockDebrisParticleSystem CreateDebrisParticleSystem(SubsystemTerrain subsystemTerrain, Vector3 position, int value, float strength)
        {

            return new MekBlockDebrisParticleSystem(subsystemTerrain, position, strength, 1f, Color.White, GetFaceTextureSlot(4, value)) { Texture = ILibrary.texture };
        }
        public virtual float GetNutritionalValue()
        {
            return 0f;
        }
        public virtual bool AllowConfigure(int face, int value)
        {
            return false;
        }
        public virtual bool Eat(ComponentVitalStats v, int value)
        {
            return false;
        }

        public virtual void OnHand(ComponentPlayer player, int value)
        {

        }
        public virtual void OnHandOut(ComponentPlayer player, int oldValue,int newValue)
        {

        }
        public virtual void OnHandIn(ComponentPlayer player, int oldValue,int newValue)
        {

        }
        public virtual DeviceType GetDeviceType()
        {
            return DeviceType.None;
        }
        public virtual void OnBlockModified(int value, int oldValue, int x, int y, int z)
        {
        }
        public virtual bool OnHitAsProjectile(CellFace? cellFace, ComponentBody componentBody, WorldItem worldItem)
        {
            return false;
        }

        public virtual void OnHitByProjectile(CellFace cellFace, WorldItem worldItem)
        {
        }
        public virtual bool OnEditBlock(int x, int y, int z, int value, ComponentPlayer componentPlayer)
        {
            return false;
        }
        public virtual void OnBlockGenerated(int value, int x, int y, int z, bool isLoaded)
        {

        }
        /// <summary>
        /// 被挖掘后执行的方法
        /// </summary>
        /// <param name="value"></param>
        /// <param name="componentMiner"></param>
        /// <param name="raycastResult"></param>
        /// <returns>true 用本方法 false 用原版方法</returns>
        public virtual bool OnDigged(int value, ComponentMiner componentMiner, TerrainRaycastResult raycastResult)
        {
            return false;
        }

        public virtual void DrawBlock(PrimitivesRenderer3D primitivesRenderer, int value, Color color, float size, ref Matrix matrix, DrawBlockEnvironmentData environmentData)
        {
            ILibrary.DrawCubeBlock(primitivesRenderer, value, new Vector3(size), ref matrix, Color.White, Color.White, environmentData);
        }
        public virtual void GenerateTerrainVertices(Block block, BlockGeometryGenerator generator, TerrainGeometry geometry, int value, int x, int y, int z)
        {
            generator.GenerateCubeVertices(block, value, x, y, z, Color.White, geometry.GetGeometry(ILibrary.texture).TransparentSubsetsByFace);
        }
        public virtual bool ShouldGenerateFace(SubsystemTerrain subsystemTerrain, int face, int value, int neighborValue)
        {
            int num = Terrain.ExtractContents(neighborValue);
            bool re = BlocksManager.Blocks[num].IsFaceTransparent(subsystemTerrain, CellFace.OppositeFace(face), neighborValue);
            return re;
        }
        public virtual int GetShadowStrength(int value)
        {
            if (IsFaceTransparent(null, 0, value)) return 0;
            else return -1;
        }
        public virtual string GetSoundMaterialName(SubsystemTerrain subsystemTerrain, int value)
        {            
            return "";
        }
        public virtual void OnNeighborBlockChanged(int x, int y, int z, int neighborX, int neighborY, int neighborZ)
        {

        }
        public static bool IsBlockEqual(int v1, int v2)
        {
            return Terrain.ExtractContents(v1) == Terrain.ExtractContents(v2) && ILibrary.GetItemId(v1) == ILibrary.GetItemId(v2);
        }
        public virtual Vector3 GetIconBlockOffset(int value, DrawBlockEnvironmentData environmentData)
        {
            return Vector3.Zero;
        }
        public virtual Vector3 GetIconViewOffset(int value, DrawBlockEnvironmentData environmentData)
        {
            return Vector3.One;
        }

        /// <summary>
        /// 使用方块
        /// </summary>
        /// <param name="start"></param>
        /// <param name="direction"></param>
        /// <param name="componentMiner"></param>
        /// <returns>false表示允许放置 true表示不允许放置</returns>
        public virtual bool OnUse(Ray3 aim, ComponentMiner componentMiner, TerrainRaycastResult? raycast)
        {
            if (raycast.HasValue)
            {
                int va = raycast.Value.Value;
                int ID = Terrain.ExtractContents(va);
                if (MekiasmInit.MekBlocks.TryGetValue(ID, out MekBlock mekBlock))
                {
                    return !mekBlock.IsInteractive(ILibrary.SubsystemTerrain, va);
                }
                return BlocksManager.Blocks[ID].IsInteractive(ILibrary.SubsystemTerrain, va);
            }
            return true;
        }

        public virtual void OnBlockAdded(SubsystemBlockBehavior blockBehavior, int value, int oldValue, int x, int y, int z)
        {

        }
        public virtual bool OnInteract(SubsystemBlockBehavior blockBehavior, TerrainRaycastResult raycastResult, ComponentMiner componentMiner)
        {
            Block block = BlocksManager.Blocks[Terrain.ExtractContents(raycastResult.Value)];
            if (block.IsInteractive(null, raycastResult.Value)) return true;
            return false;
        }
        public virtual bool IsPlaceable_(int value)
        {
            return true;
        }
        public virtual void OnBlockRemoved(SubsystemBlockBehavior blockBehavior, int value, int newValue, int x, int y, int z)
        {

        }
        public virtual void OnCollide(CellFace cellFace, float velocity, ComponentBody componentBody)
        {


        }
        /// <summary>
        /// 获得最大电量
        /// </summary>
        /// <returns></returns>
        public virtual int GetMaxPower()
        {
            return 0;
        }
        /// <summary>
        /// 获取初始电量
        /// </summary>
        /// <returns></returns>
        public virtual int GetBasePower()
        {
            return 0;
        }
        /// <summary>
        /// 方块是否可见
        /// </summary>
        /// <returns>true 可见 false不可见</returns>
        public virtual bool IsVisible(int value)
        {
            return true;
        }
        /// <summary>
        /// 当没电时消除物品
        /// </summary>
        /// <returns>true删除 false不删除</returns>
        public virtual bool IsCrushWhenNoPower()
        {
            return false;
        }
        /// <summary>
        /// 获取挖掉的方块掉落值
        /// </summary>
        /// <param name="subsystemTerrain"></param>
        /// <param name="oldValue"></param>
        /// <param name="newValue"></param>
        /// <param name="toolLevel"></param>
        /// <param name="dropValues"></param>
        /// <param name="showDebris"></param>
        public virtual void GetDropValues(SubsystemTerrain subsystemTerrain, int oldValue, int newValue, int toolLevel, List<BlockDropValue> dropValues, out bool showDebris)
        {
            showDebris = true;
            dropValues.Add(new BlockDropValue() { Value = ILibrary.setDirection(oldValue, 0), Count = 1 });
        }
        /// <summary>
        /// 获取要放置方块的值
        /// </summary>
        /// <param name="subsystemTerrain"></param>
        /// <param name="componentMiner"></param>
        /// <param name="value"></param>
        /// <param name="raycastResult"></param>
        /// <returns></returns>
        public virtual BlockPlacementData GetPlacementValue(SubsystemTerrain subsystemTerrain, ComponentMiner componentMiner, int value, TerrainRaycastResult raycastResult)
        {
            BlockPlacementData result = default;
            result.Value = value;
            result.CellFace = raycastResult.CellFace;
            return result;
        }
        /// <summary>
        /// 挖掉后的该位置的方块值
        /// </summary>
        /// <param name="subsystemTerrain"></param>
        /// <param name="componentMiner"></param>
        /// <param name="value"></param>
        /// <param name="toolValue"></param>
        /// <param name="raycastResult"></param>
        /// <returns></returns>
        public virtual BlockPlacementData GetDigValue(SubsystemTerrain subsystemTerrain, ComponentMiner componentMiner, int value, int toolValue, TerrainRaycastResult raycastResult)
        {
            BlockPlacementData result = default;
            result.Value = 0;
            result.CellFace = raycastResult.CellFace;
            return result;
        }
        public virtual string GetDescription(int value)
        {
            return "None";
        }
        public virtual string GetCategory(int value)
        {
            return Category;
        }

        public virtual bool IsInteractive(SubsystemTerrain subsystemTerrain, int value)
        {
            return false;
        }
        public virtual bool IsFaceTransparent(SubsystemTerrain subsystemTerrain, int face, int value)
        {
            return false;
        }
        public virtual string GetDisplayName(SubsystemTerrain subsystemTerrain, int value)
        {
            return DisplayName;
        }
        public virtual int GetFaceTextureSlot(int face, int value)
        {
            return 0;
        }
        public virtual BoundingBox[] GetCustomCollisionBoxes(SubsystemTerrain terrain, MovingBlock value)
        {
            return new BoundingBox[1] { new BoundingBox(Vector3.Zero, Vector3.One) };
        }
        public virtual BoundingBox[] GetCustomInteractionBoxes(SubsystemTerrain terrain, MovingBlock value)
        {
            return new BoundingBox[1] { new BoundingBox(Vector3.Zero, Vector3.One) };
        }
        public virtual float GetShovelPower(int value)
        {
            return 0.5f;
        }
        public virtual float GetQuarryPower(int value)
        {
            return 0.5f;

        }
        public virtual float GetHackPower(int value)
        {
            return 0.5f;

        }
        public virtual bool HasExtraSet(int value)
        {
            return false;
        }
        public virtual void ClickExtraSet(ComponentPlayer player, int value)
        {
        }
        public virtual bool GetExplosionIncendiary(int value)
        {
            return false;
        }
        public virtual float GetExplosionPressure(int value)
        {
            return 0f;
        }
        public virtual BlockDigMethod GetDigMethod(int value)
        {
            return BlockDigMethod.None;
        }
        public virtual float GetDigResilience(int value)
        {
            return 1f;
        }

    }
}

